<template>
  <div id="pixi-container" ref="containerRef"></div>
</template>
<script setup lang="ts">
import { useElementSize } from "@vueuse/core";
import {
  Application,
  Container,
  Assets,
  Sprite,
  DisplacementFilter,
} from "pixi.js";
import { ShockwaveFilter } from "pixi-filters";
import { getRandomNumber } from "@/utils";
const { width, height } = useElementSize(document.documentElement);
const containerRef = ref();
const app = shallowRef<Application>(new Application());
const container = shallowRef<Container>(
  new Container({
    width: width.value,
    height: height.value,
  })
);
onMounted(() => {
  render();
});
async function render() {
  await app.value.init({
    width: width.value,
    height: height.value,
    resolution: 1,
  });
  containerRef.value.appendChild(app.value.canvas);
  app.value.stage.addChild(container.value);

  const texture = await Assets.load(
    new URL("@/assets/images/IST.jpg", import.meta.url).href
  );
  // 震波纹理
  const sprite = new Sprite(texture);
  sprite.width = width.value;
  sprite.height = height.value;
  sprite.anchor.set(0.5);
  sprite.x = app.value.screen.width / 2;
  sprite.y = app.value.screen.height / 2;
  sprite.interactive = true; // 可以使用点击事件
  const displacementFilter: DisplacementFilter = await createDisplacement();
  const point = displacementFilter.scale;
  let isMax = false;
  // 震波滤镜
  const promises = await createShockwaveFilters();
  const shockwaveFilters: any = await Promise.all(promises);
  app.value.ticker.add((_ticker) => {
    if (!isMax) {
      point.x += getRandomNumber(0,0.6);
      point.y += getRandomNumber(0,0.6);
      if (point.x >= 100) isMax = true;
    } else {
      point.x -= getRandomNumber(0,0.6);
      point.y -= getRandomNumber(0,0.6);
      if (point.x <= -60) isMax = false;
    }
    shockwaveFilters.forEach((shockwaveFilter: ShockwaveFilter) => {
      createRipple(shockwaveFilter, getRandomNumber(0.8, 3));
    });
  });
  sprite.filters = [...shockwaveFilters, displacementFilter];
  container.value.addChild(sprite);
}
// 创建置换
async function createDisplacement() {
  const texture = await Assets.load(
    new URL("@/assets/images/displacement.jpg", import.meta.url).href
  );
  // 平铺精灵
  const sprite = new Sprite({
    texture,
    width: width.value,
    height: height.value,
  });
  sprite.scale = 10;
  sprite.anchor = 0.5;
  sprite.x = width.value / 2;
  sprite.y = height.value / 2;
  container.value.addChild(sprite);
  return new DisplacementFilter(sprite, 10);
}
// 创建震波滤镜
async function createShockwaveFilters() {
  const promises: any = [];
  for (let i = 0; i < 3; i++) {
    promises.push(
      new Promise((resolve) => {
        const shockwaveFilter = new ShockwaveFilter({
          center: {
            x: Math.random() * width.value,
            y: Math.random() * height.value,
          },
          radius: getRandomNumber(50, 500), //半径
          speed: getRandomNumber(200, 500), // 速度
          amplitude: getRandomNumber(30, 120), // 振幅
          wavelength: getRandomNumber(60, 200), // 波长
          brightness: getRandomNumber(1, 2.5), // 亮度
          time: 0,
        });
        resolve(shockwaveFilter);
      })
    );
  }
  return promises;
}
// 震波动画
function createRipple(filter: ShockwaveFilter, maxTime: number): void {
  filter.time += 0.005;
  if (filter.time > maxTime) {
    filter.time = 0;
    filter.center = {
      x: Math.random() * width.value,
      y: Math.random() * height.value,
    };
    createRipple(filter, maxTime);
  }
}
</script>
<style scoped>
#pixi-container {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  /* position: fixed; */
}
</style>
